package cn.smile.business.core.impl;

import cn.smile.bean.dto.core.*;
import cn.smile.bean.entity.core.SysUser;
import cn.smile.bean.form.core.user.*;
import cn.smile.bean.form.login.LoginInfoForm;
import cn.smile.business.core.ISysUserService;
import cn.smile.commons.constant.*;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.commons.enums.core.UserSexEnum;
import cn.smile.commons.enums.core.UserStatusEnum;
import cn.smile.commons.enums.core.UserTypeEnum;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.repository.core.SysUserMapper;
import cn.smile.utils.*;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @author smile-jt
 */
@Slf4j
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Resource
    private RedisUtil redisUtil;

    @Override
    public SysUserDTO queryByLogin(String loginId) {
        log.info("[SysUserServiceImpl].[queryByLogin] ------> 根据登陆ID查询用户信息 Start, loginId = {}", loginId);
        SysUserDTO dto = null;
        if (!ObjectUtils.isEmpty(loginId)) {
            SysUser user = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getLoginId, loginId));
            if (!ObjectUtils.isEmpty(user)) {
                dto = BeanCopy.copyBean(user, SysUserDTO.class);
            }
        }
        log.info("[SysUserServiceImpl].[queryByLogin] ------> 根据登陆ID查询用户信息 End, dto = {}", ObjectUtils.isEmpty(dto) ? null : JSON.toJSONString(dto));
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateLoginTime(LoginInfoForm form) {
        log.info("[SysUserServiceImpl].[queryByLogin] ------> 更新用户最后登陆信息 Start, form = {}", JSON.toJSONString(form));
        SysUser user = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getId, form.getId()));
        user.setLastLoginAdd(form.getLastLoginAddress());
        user.setLastLoginTime(LocalDateTime.now());
        super.updateBaseCol(user);
        int updateNum = baseMapper.updateById(user);
        log.info("[SysUserServiceImpl].[queryByLogin] ------> 更新用户最后登陆信息 End, updateNum = {}", updateNum);
        return updateNum > NumberConstant.ZERO;
    }

    @Override
    public IPage<SysUserDTO> queryPage(QueryUserForm form) {
        log.info("[SysUserServiceImpl].[queryPage] ------> 分页查询用户 Start, form = {}", JSON.toJSONString(form));
        LambdaQueryWrapper<SysUser> queryParams = this.getQueryParams(form);
        queryParams.eq(SysUser::getIsShow, Boolean.TRUE);
        Page<SysUser> dataPage = baseMapper.selectPage(form.queryPage(), queryParams);
        IPage<SysUserDTO> resultData = BeanCopy.copyPage(dataPage, SysUserDTO.class);
        this.setUserDetail(resultData.getRecords());
        log.info("[SysUserServiceImpl].[queryPage] ------> 分页查询用户 End");
        return resultData;
    }

    @Override
    public List<SysUserDTO> queryList(QueryUserForm form) {
        log.info("[SysUserServiceImpl].[queryList] ------> 列表查询用户 Start, form = {}", JSON.toJSONString(form));
        List<SysUser> dataPage = baseMapper.selectList(this.getQueryParams(form));
        List<SysUserDTO> result = BeanCopy.copyList(dataPage, SysUserDTO.class);
        log.info("[SysUserServiceImpl].[queryList] ------> 列表查询用户 End");
        return result;
    }

    @Override
    public Map<String, SysUserDTO> queryUserMap(QueryUserForm form) {
        log.info("[SysUserServiceImpl].[queryUserMap] ------> Map集合查询用户 Start, form = {}", JSON.toJSONString(form));
        Map<String, SysUserDTO> userMap = Maps.newHashMap();
        List<SysUserDTO> userList = this.queryList(form);
        if (!CollectionUtils.isEmpty(userList)) {
            userList.forEach(user -> userMap.put(user.getId(), user));
        }
        log.info("[SysUserServiceImpl].[queryUserMap] ------> Map集合查询用户 End");
        return userMap;
    }

    @Override
    public String encode(String temp) {
        log.info("[SysUserServiceImpl].[encode] ------> 字符串加密 Start, temp = {}", temp);
        String encode = PasswordUtil.encrypt(temp);
        log.info("[SysUserServiceImpl].[encode] ------> 字符串加密 End, encode = {}", encode);
        return encode;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean registerUser(HttpServletRequest request, RegisterUserForm form) {
        String ip = IpUtils.getRemoteIp(request);
        log.info("请求IP = {}", ip);
        this.checkRegisterForm(ip, form);
        return this.registerUser(form);
    }

    @Override
    public Boolean registerUser(RegisterUserForm form) {
        log.info("[SysUserServiceImpl].[registerUser] ------> 注册用户 Start, form = {}", JSON.toJSONString(form));
        SysUser user = BeanCopy.copyBean(form, SysUser.class);
        user.setPassword(this.encode(form.getPassword()));
        super.addBaseCol(user);
        user.setAvatar(CommonConstant.DEFAULT_AVATAR_URL);
        user.setStatus(UserStatusEnum.ENABLE.getSn());
        user.setUserType(UserTypeEnum.USER.getSn());
        int insertNum = baseMapper.insert(user);
        log.info("[SysUserServiceImpl].[registerUser] ------> 注册用户 End, insertNum = {}", insertNum);
        return insertNum > NumberConstant.ZERO;
    }

    @Override
    public Boolean checkLoginId(String loginId) {
        log.info("[SysUserServiceImpl].[checkLoginId] ------> 检查登录ID是否存在 Start, loginId = {}", loginId);
        List<SysUser> dataList = baseMapper.selectList(new QueryWrapper<SysUser>().lambda().eq(SysUser::getDeleted, Boolean.FALSE).eq(SysUser::getLoginId, loginId));
        boolean result = !CollectionUtils.isEmpty(dataList);
        log.info("[SysUserServiceImpl].[checkLoginId] ------> 检查登录ID是否存在 End, result = {}", result);
        return result;
    }

    @Override
    public void resetTourist() {
        log.info("[SysUserServiceImpl].[resetTourist] ------> 重置游客用户信息 Start");
        SysUser user = this.baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getId, TouristResetConstant.USER_ID).eq(SysUser::getDeleted, Boolean.FALSE));
        if (!ObjectUtils.isEmpty(user)) {
            user.setAvatar(CommonConstant.DEFAULT_AVATAR_URL);
            user.setLoginId(TouristResetConstant.LOGIN_ID);
            user.setSignature(TouristResetConstant.SIGNATURE);
            user.setNickName(TouristResetConstant.NICK_NAME);
            user.setPassword(TouristResetConstant.PASSWORD);
            super.updateBaseCol(user);
            baseMapper.updateById(user);
        }
        log.info("[SysUserServiceImpl].[resetTourist] ------> 重置游客用户信息 End");
    }

    @Override
    public SysUserDTO getUserInfo() {
        log.info("[SysUserServiceImpl].[getUserInfo] ------> 获取登录用户信息 Start");
        SysUser user = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getId, UserUtil.getUserInfo().getId()).eq(SysUser::getDeleted, Boolean.FALSE));
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        SysUserDTO dto = BeanCopy.copyBean(user, SysUserDTO.class);
        //密码置空
        dto.setPassword(null);
        if (!ObjectUtils.isEmpty(dto.getGender())) {
            dto.setGenderRadioFlag(String.valueOf(dto.getGender()));
        } else {
            dto.setGenderRadioFlag(String.valueOf(NumberConstant.ZERO));
        }
        log.info("[SysUserServiceImpl].[getUserInfo] ------> 获取登录用户信息 End");
        return dto;
    }

    @Override
    public Boolean changeAvatar(ChangeAvatarForm form) {
        log.info("[SysUserServiceImpl].[changeAvatar] ------> 更新用户头像 Start, form = {}", JSON.toJSONString(form));
        SysUser entity = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getDeleted, Boolean.FALSE).eq(SysUser::getId, UserUtil.getUserInfo().getId()));
        if (ObjectUtils.isEmpty(entity)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        entity.setAvatar(form.getAvatar());
        super.updateBaseCol(entity);
        int updateNum = baseMapper.updateById(entity);
        log.info("[SysUserServiceImpl].[changeAvatar] ------> 更新用户头像 End, updateNum = {}", updateNum);
        return updateNum > NumberConstant.ZERO;
    }

    @Override
    public Boolean updateLoginPwd(UpdatePwdForm form) {
        log.info("[SysUserServiceImpl].[updateLoginPwd] ------> 登陆用户修改密码 Start, form = {}", JSON.toJSONString(form));
        SysUser user = this.checkPwd(form);
        super.updateBaseCol(user);
        int updateNum = baseMapper.updateById(user);
        log.info("[SysUserServiceImpl].[updateLoginPwd] ------> 登陆用户修改密码 End, updateNum = {}", updateNum);
        return updateNum > NumberConstant.ZERO;
    }

    @Override
    public Boolean updateUserBase(UpdateUserBaseForm form) {
        log.info("[SysUserServiceImpl].[updateUserBase] ------> 更新用户基本信息 Start, form = {}", JSON.toJSONString(form));
        SysUser user = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getDeleted, Boolean.FALSE).eq(SysUser::getId, form.getId()));
        user.setNickName(form.getNickName());
        user.setGender(Integer.parseInt(form.getGenderRadioFlag()));
        user.setSignature(form.getSignature());
        super.updateBaseCol(user);
        int updateNum = baseMapper.updateById(user);
        log.info("[SysUserServiceImpl].[updateUserBase] ------> 更新用户基本信息 End, updateNum = {}", updateNum);
        return updateNum > NumberConstant.ZERO;
    }

    @Override
    public List<SysUserDTO> getAllEnableUser() {
        log.info("[SysUserServiceImpl].[getAllEnableUser] ------> 查询全部启用账户 Start");
        List<SysUser> baseList = baseMapper.selectList(new QueryWrapper<SysUser>().lambda().eq(SysUser::getDeleted, Boolean.FALSE).eq(SysUser::getStatus, UserStatusEnum.ENABLE.getSn()));
        List<SysUserDTO> dataList = BeanCopy.copyList(baseList, SysUserDTO.class);
        log.info("[SysUserServiceImpl].[getAllEnableUser] ------> 查询全部启用账户 End");
        return dataList;
    }

    /**
     * 检查密码
     *
     * @param form 检查参数
     */
    private SysUser checkPwd(UpdatePwdForm form) {
        if (!form.getNewPwd().equals(form.getConfirmPwd())) {
            throw new BusinessException(MyResponseCode.CONFIRM_PASSWORD_ERROR);
        }
        if (form.getNewPwd().equals(form.getOldPwd())) {
            throw new BusinessException(MyResponseCode.NO_CHANGE_PASSWORD_ERROR);
        }
        SysUser user = baseMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getId, UserUtil.getUserInfo().getId()).eq(SysUser::getDeleted, Boolean.FALSE));
        if (ObjectUtils.isEmpty(user)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        String oldEncode = this.encode(form.getOldPwd());
        if (!oldEncode.equals(user.getPassword())) {
            throw new BusinessException(MyResponseCode.OLD_PASSWORD_ERROR);
        }
        user.setPassword(this.encode(form.getNewPwd()));
        return user;
    }

    /**
     * 写入用户详情信息
     *
     * @param dataList 用户集合
     */
    private void setUserDetail(List<SysUserDTO> dataList) {
        if (!CollectionUtils.isEmpty(dataList)) {
            for (SysUserDTO user : dataList) {
                user.setGenderText(UserSexEnum.get(user.getGender()).getMsg());
                user.setStatusText(UserStatusEnum.get(user.getStatus()).getMsg());
            }
        }
    }

    /**
     * 获取列表查询参数
     *
     * @param form 查询参数
     * @return 查询对象
     */
    private LambdaQueryWrapper<SysUser> getQueryParams(QueryUserForm form) {
        LambdaQueryWrapper<SysUser> qw = new QueryWrapper<SysUser>().lambda().eq(SysUser::getDeleted, Boolean.FALSE);
        if (!ObjectUtils.isEmpty(form.getNickName())) {
            qw.like(SysUser::getNickName, form.getNickName());
        }
        if (!CollectionUtils.isEmpty(form.getIds())) {
            qw.in(SysUser::getId, form.getIds());
        }
        return qw;
    }

    /**
     * 验证注册参数
     *
     * @param ip   IP
     * @param form 请求参数
     */
    private void checkRegisterForm(String ip, RegisterUserForm form) {
        Object bucket = redisUtil.get(String.format(RedisKeyConstant.USER_REGISTER_KEY, ip));
        RegisterRedisDTO registerNum;
        //验证接口请求次数是否两小时达到5次
        if (!ObjectUtils.isEmpty(bucket)) {
            registerNum = JSON.parseObject(bucket.toString(), RegisterRedisDTO.class);
            if (NumberConstant.FIVE == registerNum.getNum()) {
                throw new BusinessException(MyResponseCode.REGISTER_USER_ERROR);
            }
        } else {
            registerNum = new RegisterRedisDTO();
            registerNum.setNum(NumberConstant.ZERO);
        }
        //注册, 请求次数+1
        registerNum.setNum(registerNum.getNum() + NumberConstant.ONE);
        redisUtil.set(String.format(RedisKeyConstant.USER_REGISTER_KEY, ip), JSON.toJSONString(registerNum), RedisKeyConstant.USER_REGISTER_TIMEOUT);
        //验证手机号是否存在
        if (this.checkLoginId(form.getLoginId())) {
            throw new BusinessException(MyResponseCode.LOGIN_ID_EXIST_ERROR);
        }
        //未填写用户昵称, 写入默认用户名
        if (ObjectUtils.isEmpty(form.getNickName())) {
            form.setNickName(String.format(CommonConstant.DEFAULT_NICK_NAME, PasswordUtil.randomLoginId(NumberConstant.FOUR)));
        }
    }
}